package com.huiyun.project.pay.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huiyun.project.common.core.util.NumUtils;
import com.huiyun.project.common.core.util.WebUtils;
import com.huiyun.project.common.sequence.IdUtils;
import com.huiyun.project.pay.biz.dto.PayOrderDto;
import com.huiyun.project.pay.biz.entity.MchInfo;
import com.huiyun.project.pay.biz.entity.PayChannel;
import com.huiyun.project.pay.biz.entity.PayOrder;
import com.huiyun.project.pay.biz.service.MchInfoService;
import com.huiyun.project.pay.biz.service.PayChannelService;
import com.huiyun.project.pay.biz.service.PayOrderService;
import com.huiyun.project.pay.biz.utils.PayUtils;
import com.huiyun.project.pay.client.consts.PayConst;
import com.huiyun.project.pay.client.vo.PayReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;

/**
 * @author tiger
 */
@Slf4j
public class BaseController {
    @Autowired
    protected PayOrderService payOrderService;
    @Autowired
    protected MchInfoService mchInfoService;
    @Autowired
    protected PayChannelService payChannelService;

    /**
     * 创建支付订单
     *
     * @param params
     * @return
     */
    protected PayOrderDto createPayOrder(PayReq params) {
        log.info("-------------[商户统一下单]创建支付订单开始-------------");
        // 验证参数有效性
        PayOrderDto payOrderDto = new PayOrderDto();
        BeanUtil.copyProperties(params, payOrderDto);
        //ip地址
        payOrderDto.setClientIp(WebUtils.getIP());
        PayOrder payOrder = validateParams(payOrderDto);
        payOrderService.savePayOrder(payOrder);
        return payOrderDto;
    }


    /**
     * 验证创建订单请求参数,参数通过返回JSONObject对象,否则返回错误文本信息
     *
     * @param params
     * @return
     */
    private PayOrder validateParams(PayOrderDto params) {
        log.info("-------------[商户统一下单]开始验证统一下单参数-------------");
        // 验证请求参数,参数有问题返回错误提示
        String extra = params.getExtra();
        String sign = params.getSign();
        String channelId = params.getChannelId();
        // 验证请求参数有效性（必选项）
        Assert.notBlank(params.getMchId(), "request params[mchId] error.");
        Assert.notBlank(params.getMchOrderNo(), "request params[mchOrderNo] error.");
        Assert.notBlank(params.getChannelId(), "request params[channelId] error.");
        Assert.isTrue(params.getAmount() != null, "request params[amount] error.");
        Assert.notBlank(params.getCurrency(), "request params[currency] error.");
        Assert.notBlank(params.getSubject(), "request params[subject] error.");
        Assert.notBlank(params.getBody(), "request params[body] error.");

        // 根据不同渠道,判断extra参数
        if (PayConst.PAY_CHANNEL_WX_JSAPI.equalsIgnoreCase(params.getChannelId())) {
            Assert.notEmpty(extra, "request params[extra] error.");
            JSONObject extraObject = JSON.parseObject(extra);
            String openId = extraObject.getString("openId");
            Assert.notBlank(openId, "request params[extra.openId] error.");
        } else if (PayConst.PAY_CHANNEL_WX_NATIVE.equalsIgnoreCase(params.getChannelId())) {
            Assert.notEmpty(extra, "request params[extra] error.");
            JSONObject extraObject = JSON.parseObject(extra);
            String productId = extraObject.getString("productId");
            Assert.notBlank(productId, "request params[extra.productId] error.");
        } else if (PayConst.PAY_CHANNEL_WX_MWEB.equalsIgnoreCase(params.getChannelId())) {
            Assert.notEmpty(extra, "request params[extra] error.");
            JSONObject extraObject = JSON.parseObject(extra);
            String sceneInfo = extraObject.getString("sceneInfo");
            Assert.notBlank(sceneInfo, "request params[extra.sceneInfo] error.");
        }else if (PayConst.PAY_CHANNEL_ALIPAY_QR.equalsIgnoreCase(params.getChannelId())) {
            //商户扫客户条码 需要传支付码
            Assert.notEmpty(params.getParam1(), "request params[param1] error. qr pay need auth_code");
        }


        // 查询商户信息
        MchInfo mchInfo = mchInfoService.getById(params.getMchId());
        Assert.notNull(mchInfo, "Can't found mchInfo[mchId=" + params.getMchId() + "] record in db.");
        Assert.isTrue(NumUtils.eq(mchInfo.getState(), 1), "mchInfo not available [mchId=" + params.getMchId() + "] record in db.");


        // 查询商户对应的支付渠道
        PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(params.getMchId(), params.getChannelAppId());
        Assert.notNull(payChannel, "Can't found payChannel[channelId=" + channelId + ",mchId=" + params.getMchId() + "] record in db.");

        Assert.isTrue(NumUtils.eq(payChannel.getState(), 1), "channel not available [channelId=" + channelId + ",mchId=" + params.getMchId() + "]");


        String reqKey = mchInfo.getReqKey();
        //不验证签名
        if (StrUtil.isNotBlank(reqKey)) {
            // 签名信息
            Assert.notEmpty(sign, "request params[sign] error.");
            // 验证签名数据
            boolean verifyFlag = PayUtils.verifyPaySign(BeanUtil.beanToMap(params), reqKey);
            Assert.isTrue(verifyFlag, "Verify XX pay sign failed.");
        }


        /**
         * 上下文信息传递
         */
        params.setResKey(mchInfo.getResKey());

        // 验证参数通过,返回PayOrder对象
        PayOrder payOrder = new PayOrder();
        Date now = new Date();
        BeanUtil.copyProperties(params, payOrder);
        payOrder.setId(Convert.toStr(IdUtils.getId()));
        payOrder.setChannelMchId(payChannel.getChannelMchId());
        payOrder.setCreateTime(now);
        payOrder.setUpdateTime(now);
        return payOrder;
    }
}
